﻿
//#define USE_PARTICLE_SYSTEM

using OWL.Rendering.HRP;
using System.Collections.Generic;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.ParticleSystemJobs;
using UnityEngine.Profiling;
using Yoozoo.Gameplay.RTS;
using Yoozoo.Managers.ResourceManagerV2.Framework;
using Random = UnityEngine.Random;

namespace Yoozoo.Mars.Got.SpriteAnim
{
    public struct AnimInfoData
    {
        public float labelLifeTime;
        public float duration;
    }


    public struct AnimInfoDataArray
    {
        public AnimInfoData[] animData; //N个方向的
    }

    // 
    public struct SpriteAnimData
    {
        //index : action(0-xx)
        public Dictionary<SPRITE_ACTION_ENUM, AnimInfoDataArray> spriteData;
    }

    public class AnimSpriteCreator
    {
        private const float ANIM_PIXEL_PER_UNIT = 57;
        private const float FRAME_PER_SECOND = 30;
        private const int DURATION_EXTEND = 100;
        public const int MAX_SPRITE_DIRECTION = 9; 
        private const int MAX_SPRITE_ACTION = 26;
        private const int MAX_ANIM_FRAMES = 100;
#if USE_PARTICLE_SYSTEM
        private ParticleSystem ptSystem;
        private ParticleSystem.Particle[] particlePool;
        private ParticleSystemRenderer pRenderer;
        private float allLifeTime = 0;
#else
        private NativeArray<Matrix4x4> matrices;
        private Matrix4x4[] cacheMatrices;
        private MaterialPropertyBlock mbp;
#endif
        private List<SpriteVisitor> GOTSpritePool;
        private List<System.Action> completionCallbacks;
        private GameObject systemGo;

        private string altasName = null;

        //public Dictionary<int, Dictionary<SPRITE_ACTION_ENUM, AnimInfoData[]>> SpriteDic;
        public Dictionary<int, SpriteAnimData> SpriteDicEx;
        //public SpriteAnimData SpriteAnimData;
        private int particleCount = 0;
        private float offest;

        private SpriteFrameController frameController;
        private SpriteResourceManager resourceManager;

        private Material particlesMaterial = null;
        private Vector3 rotation3D;

        private static int visitKey = -1;
        private bool haveUsed = false;

        private int poolLength;

        public static Mesh s_mesh;
        
        /// <summary>
        /// 现在默认是5方向，需要反转
        /// </summary>
        private bool needFlip = true;

        public int ParticleCount
        {
            get { return particleCount; }
        }

        public int SpritesLength
        {
            get {
#if USE_PARTICLE_SYSTEM
                return particlePool.Length;
#else
                return matrices.Length;
#endif
            }
        }

        public string CreatorName
        {
            get { return systemGo.name; }
        }

        public string AltasName
        {
            get { return altasName; }
        }

        public Transform Transform
        {
            get { return systemGo.transform; }
        }

        public float SizeOffset
        {
            get { return offest; }
        }

        public Material ParticlesMaterial
        {
            get { return particlesMaterial; }
        }

        public string CreatorOriginName;
        public int CreatorTeam;
        
        /// <summary>
        /// 是否16方向,index是动作
        /// </summary>
        public NativeArray<bool> isDirect16;
        protected void SetVisitKey(int key)
        {
            if (visitKey == -1)
                visitKey = key;
        }

        protected void Dispose()
        {
            this.CompleteJob();
#if USE_PARTICLE_SYSTEM
            ptSystem = null;
            particlePool = null;
            pRenderer = null;
#else
            matrices.Dispose();
#endif
            foreach (SpriteVisitor item in GOTSpritePool)
            {
                item.Dispose_v();
            }
            GOTSpritePool.Clear();
            GOTSpritePool = null;
            systemGo = null;
            //SpriteDic.Clear();
            //SpriteDic = null;
            SpriteDicEx.Clear();
            SpriteDicEx = null;
            frameController = null;
            particlesMaterial = null;

            DisposeNativeArrays();
        }

        private bool isSpecialCountAtlas = false;
        private int specialCountAtlasOffset = 0;
        
        protected AnimSpriteCreator(Interface_AnimSpriteSupportTemplate interface_direct, GameObject go,
            string m_altasName, Material m_material, int initialCount, BaseSpriteCache spriteCache)
        {
            //SpriteDic = new Dictionary<int, Dictionary<SPRITE_ACTION_ENUM, AnimInfoData[]>>();
            //isDirect16 = BattleUtils.IsCar(m_altasName
            isDirect16 = new NativeArray<bool>(MAX_SPRITE_ACTION,Allocator.Persistent);
            SpriteDicEx = new Dictionary<int, SpriteAnimData>();
            frameController = new SpriteFrameController(interface_direct);
            resourceManager = new SpriteResourceManager(spriteCache);
#if USE_PARTICLE_SYSTEM
            ptSystem = go.GetComponent<ParticleSystem>();
            pRenderer = (ParticleSystemRenderer) ptSystem.GetComponent<Renderer>();
            pRenderer.EnableVertexStreams(ParticleSystemVertexStreams.Custom1);
            pRenderer.EnableVertexStreams(ParticleSystemVertexStreams.Custom2);
            pRenderer.lengthScale = 1f;
            pRenderer.velocityScale = 1f;
#endif
            rotation3D = interface_direct.GetBillBoardRotation();
            particlesMaterial = m_material;
            altasName = m_altasName;

            needFlip = true;
            GOTSpritePool = new List<SpriteVisitor>(500);
            completionCallbacks = new List<System.Action>();
            particleCount = 0;
            var maxParticles = SpriteParticleSystemManager.INITAL_PARTICLE_NUM;
            maxParticles = (int)(maxParticles * BattleUtils.NativeArrayInitRatio);
            poolLength = maxParticles;
    
            systemGo = go;
#if USE_PARTICLE_SYSTEM
            pRenderer.renderMode = ParticleSystemRenderMode.Billboard;
            pRenderer.material = m_material;
            var ptSystemMain = ptSystem.main;
            
            //设置初始化的池子大小
            particlePool = new ParticleSystem.Particle[poolLength];
            ptSystemMain.maxParticles = maxParticles;
            if (particleCount == 0)
            {
                systemGo.SetActive(false);
                ParticleSystem.TextureSheetAnimationModule sheet = ptSystem.textureSheetAnimation;
                for (int index = sheet.spriteCount - 1; index >= 0; index--)
                {
                    sheet.RemoveSprite(index);
                }
            }
#else
            systemGo.SetActive(false);
            matrices = new NativeArray<Matrix4x4>(poolLength, Allocator.Persistent);
            particlesMaterial.enableInstancing = true;
            //particlesMaterial.renderQueue = 2450;
            particlesMaterial.EnableKeyword( "OPT_DRAW_INSTANCED_TROOP" );
#endif

            data = new AnimSpriteCreatorData();
            data.alphas = new NativeArray<byte>(maxParticles, Allocator.Persistent);
            data.actions = new NativeArray<int>(maxParticles, Allocator.Persistent);
            data.rotations = new NativeArray<float3>(maxParticles, Allocator.Persistent);
            data.speeds = new NativeArray<float>(maxParticles, Allocator.Persistent);
            data.positions = new NativeArray<float3>(maxParticles, Allocator.Persistent);
            data.offsets = new NativeArray<float3>(maxParticles, Allocator.Persistent);
            data.spriteSizes = new NativeArray<float>(maxParticles, Allocator.Persistent);
            data.restarts = new NativeArray<bool>(maxParticles, Allocator.Persistent);
            data.removes = new NativeArray<bool>(maxParticles, Allocator.Persistent);
            data.colorOffset = new NativeArray<float4>(maxParticles, Allocator.Persistent);
            data.team = new NativeArray<int>(maxParticles, Allocator.Persistent);
            
            for (int i = 0; i < maxParticles; i++)
            {
                data.alphas[i] = 255;
                data.actions[i] = (int) SPRITE_ACTION_ENUM.IDLE;
                data.spriteSizes[i] = 0.8f;
                data.speeds[i] = 1f;
            }
            // 用来存放动画的开始和结束时间
            int totalAnimations = MAX_SPRITE_ACTION * MAX_SPRITE_DIRECTION;
#if USE_PARTICLE_SYSTEM
            startAliveTimePercents = new NativeArray<float>(totalAnimations, Allocator.Persistent);
            endAliveTimePercents = new NativeArray<float>(totalAnimations, Allocator.Persistent);
            realAliveTimePercents = new NativeArray<float>(maxParticles, Allocator.Persistent);
#else
            var totalFrameCount = totalAnimations * MAX_ANIM_FRAMES;
            spriteAnimTextureRect = new NativeArray<float4>(totalFrameCount, Allocator.Persistent);
            spriteAnimFrameSize = new NativeArray<float2>(totalFrameCount, Allocator.Persistent);
            spriteAnimFrameOffset = new NativeArray<float2>(totalFrameCount, Allocator.Persistent);
            spriteAnimFrameCount = new NativeArray<int>(totalAnimations, Allocator.Persistent);
            spriteCurrentFrame = new NativeArray<int>(maxParticles, Allocator.Persistent);
            spriteTimeLeft = new NativeArray<float>(maxParticles, Allocator.Persistent);
#endif

            isSpecialCountAtlas = BaseSpriteCache.specialMaskCountSprite.ContainsKey(m_altasName);
            var offsetCount = totalFrameCount;
            if (isSpecialCountAtlas)
            {
                offsetCount *= 2;
                specialCountAtlasOffset = totalFrameCount;
            }
            changeColorOffsetX = new NativeArray<float>(offsetCount,Allocator.Persistent);
            changeColorOffsetY = new NativeArray<float>(offsetCount,Allocator.Persistent);
            changeColorOffsetX2 = new NativeArray<float>(offsetCount,Allocator.Persistent);
            changeColorOffsetY2 = new NativeArray<float>(offsetCount,Allocator.Persistent);
            
            startOffsetX = new NativeArray<float>(totalAnimations * MAX_ANIM_FRAMES,Allocator.Persistent);
            startOffsetY = new NativeArray<float>(totalAnimations * MAX_ANIM_FRAMES,Allocator.Persistent);
            rectWidth = new NativeArray<float>(totalAnimations * MAX_ANIM_FRAMES, Allocator.Persistent);
            rectHeight = new NativeArray<float>(totalAnimations * MAX_ANIM_FRAMES, Allocator.Persistent);
            
            ParticleJobHelper.Initialize();
            //把队伍设置成独立相机渲染，防止队伍角色受后效影响
            go.layer = LayerMask.NameToLayer("MarchHud");
            //名字最后一位表示阵营
            var name = go.name;
            var lastLetter = name.Substring(name.Length - 1, 1);
            if (int.TryParse(lastLetter, out CreatorTeam))
            {
                CreatorOriginName = name.Substring(0, name.Length - 1);
            }
            else
            {
                CreatorOriginName = string.Empty;
                CreatorTeam = -1;
            }
        }

        public void ExpendArrays()
        {
            Profiler.BeginSample("AnimSpriteCreator.ExpendArrays");
            //先检测扩容以后是否超过了最大数量
            var newPoolLength = Mathf.Min(poolLength * 2,SpriteParticleSystemManager.INITAL_PARTICLE_NUM);
            if (poolLength == newPoolLength)
            {
                Debug.LogError(CreatorName+"满了");
                return;
            }
            poolLength = newPoolLength;
            
            var maxParticles = poolLength;

            var data = this.data;
            data.alphas = BattleUtils.GetExpendedArray(data.alphas, maxParticles);
            data.actions = BattleUtils.GetExpendedArray(data.actions, maxParticles);
            data.rotations = BattleUtils.GetExpendedArray(data.rotations, maxParticles);
            data.speeds = BattleUtils.GetExpendedArray(data.speeds, maxParticles);
            data.positions = BattleUtils.GetExpendedArray(data.positions, maxParticles);
            data.offsets = BattleUtils.GetExpendedArray(data.offsets, maxParticles);
            data.spriteSizes = BattleUtils.GetExpendedArray(data.spriteSizes, maxParticles);
            data.restarts = BattleUtils.GetExpendedArray(data.restarts, maxParticles);
            data.removes = BattleUtils.GetExpendedArray(data.removes, maxParticles);
            data.colorOffset = BattleUtils.GetExpendedArray(data.colorOffset, maxParticles);
            data.team = BattleUtils.GetExpendedArray(data.team, maxParticles);
            this.data = data;
            
            //Debug.LogError("sprite扩容");
            //通知部队那边更新数组引用
            SquareDataManager.Instance.OnSpriteCreatorArrayChanged(CreatorName,this.data);

#if USE_PARTICLE_SYSTEM
            var main = ptSystem.main;
            main.maxParticles = maxParticles;
            ParticleSystem.Particle[] all = new ParticleSystem.Particle[poolLength];
            for (int i = 0; i < particlePool.Length; i++)
            {
                all[i] = particlePool[i];
            }

            particlePool = all; //all.ToAr
#else
            matrices = BattleUtils.GetExpendedArray(matrices, maxParticles);
            spriteCurrentFrame = BattleUtils.GetExpendedArray(spriteCurrentFrame, maxParticles);
            spriteTimeLeft = BattleUtils.GetExpendedArray(spriteTimeLeft, maxParticles);
#endif
            Profiler.EndSample();
        }


        private void DisposeNativeArrays()
        {
#if USE_PARTICLE_SYSTEM
            startAliveTimePercents.Dispose();
            endAliveTimePercents.Dispose();
            realAliveTimePercents.Dispose();
#else
            spriteAnimTextureRect.Dispose();
            spriteAnimFrameSize.Dispose();
            spriteAnimFrameOffset.Dispose();
            spriteAnimFrameCount.Dispose();
            spriteCurrentFrame.Dispose();
            spriteTimeLeft.Dispose();
#endif
            changeColorOffsetX.Dispose();
            changeColorOffsetY.Dispose();
            changeColorOffsetX2.Dispose();
            changeColorOffsetY2.Dispose();
            startOffsetX.Dispose();
            startOffsetY.Dispose();
            rectWidth.Dispose();
            rectHeight.Dispose();
            isDirect16.Dispose();
            data.alphas.Dispose();
            data.actions.Dispose();
            data.rotations.Dispose();
            data.speeds.Dispose();
            data.positions.Dispose();
            data.offsets.Dispose();
            data.spriteSizes.Dispose();
            data.restarts.Dispose();
            data.team.Dispose();
            data.removes.Dispose();
            data.colorOffset.Dispose();
        }

        protected void SetRanderPriority(float priority)
        {
#if USE_PARTICLE_SYSTEM
            pRenderer.sortingFudge = -1 * priority;
#endif
        }

        protected void SetRendererPriority(int priority)
        {
#if USE_PARTICLE_SYSTEM
            pRenderer.sharedMaterial.renderQueue = priority;
            //pRenderer.rendererPriority = priority;
#endif
        }

        protected void SetPropertyBlock(MaterialPropertyBlock block)
        {
#if USE_PARTICLE_SYSTEM
            pRenderer.SetPropertyBlock(block);
#else
            mbp = block;
#endif
        }

        protected void GetPropertyBlock(MaterialPropertyBlock block)
        {
#if USE_PARTICLE_SYSTEM
            pRenderer.GetPropertyBlock(block);
#else
            block = mbp;
#endif
        }
        public void SetRenderEnable(bool enable)
        {
#if USE_PARTICLE_SYSTEM
            pRenderer.enabled = enable;
#endif
        }
        protected void RemoveTextureSheetAnimation()
        {
#if USE_PARTICLE_SYSTEM
            particlesMaterial.mainTexture = null;
            ParticleSystem.TextureSheetAnimationModule sheet = ptSystem.textureSheetAnimation;
            for (int index = sheet.spriteCount - 1; index >= 0; index--)
            {
                sheet.RemoveSprite(index);
            }

            resourceManager.SetSpritesNotUseTag(AltasName);
#endif
        }

        protected void SetTextureSheetAnimation(bool sync)
        {
            SpriteAnimationX spritesAnimationX = resourceManager.GetSprites(AltasName);
            particlesMaterial.mainTexture = spritesAnimationX.texture;
#if USE_PARTICLE_SYSTEM
            ParticleSystem.TextureSheetAnimationModule sheet = ptSystem.textureSheetAnimation;
            //？？说明已经拿到了？？
            if (sheet.spriteCount != 0)
            {
                return;
            }
            if (AltasName == "shadow")
            {
                sheet.enabled = false;
            }
            sheet.frameOverTimeMultiplier = 1;
            sheet.cycleCount = 1;
#endif

            offest = spritesAnimationX.scale;
            if (CreatorName != "soilder_Idle" && CreatorName != "gta_soilder_Batterer_1")
            {
                SquareDataManager.Instance?.UpdateSpriteCreatorScale(CreatorName, offest);
            }

            AnimInfoData[] sprites_cache = null;
            
            //SpriteAnimData = new SpriteAnimData {spriteData = new Dictionary<SPRITE_ACTION_ENUM, AnimInfoDataArray>()};
            AnimInfoDataArray tempAnimInfoArr;
            int animIndex = 0;
            int actionNum = spritesAnimationX.actions.Count;
            //序列帧总的生命周期
#if USE_PARTICLE_SYSTEM
            allLifeTime = (spritesAnimationX.totalFrameCount) / FRAME_PER_SECOND * DURATION_EXTEND;
            float startTime = 0;
#endif
            int directionCount;
            int recIndex;
            for(int actionKey = 0;  actionKey < MAX_SPRITE_ACTION; actionKey++)
            {
                SpriteAnimationAction spAnimationAction;
                if (!spritesAnimationX.actions.TryGetValue(SpriteFrameController.GetAnimationNameByActionEnum((SPRITE_ACTION_ENUM)actionKey), out spAnimationAction))
                {
                    continue;
                }
                animIndex++;
                //这个用于判断一个动作的8个方向是不是结束了。。。
                directionCount = spAnimationAction.directionSpList.Count;
                tempAnimInfoArr = new AnimInfoDataArray();
                sprites_cache = new AnimInfoData[MAX_SPRITE_DIRECTION];
                tempAnimInfoArr.animData = sprites_cache;

               // SPRITE_ACTION_ENUM actionEnum = (SPRITE_ACTION_ENUM)actionKey;
                //SpriteAnimData.spriteData[actionEnum] = tempAnimInfoArr;
                isDirect16[actionKey] = directionCount == MAX_SPRITE_DIRECTION;
                recIndex = 0;
                for(int directionKey = 0 ; directionKey < MAX_SPRITE_DIRECTION; directionKey++)
                //foreach (var directionKey in spAnimationAction.directionSpList.Keys)
                {
                     
                        //这里的方向是按照序列帧给的方向来的
                        // 一个方向的所有序列帧
                        Dictionary<int,SpriteData> spList;
                        if (spAnimationAction.directionSpList.TryGetValue(directionKey, out spList)) // 如果有这个方向的动画
                        {
                            recIndex++;
                            int spLen = spList.Count;
                            Sprite sp;
                            for(int framesNum = 0; framesNum < spLen; framesNum++)// 一个方向的每一帧
                            {
                                var data = spList[framesNum];
                                sp = data.sprite;
                               // Debug.Log($"Sprite: {spritesAnimationX.assetName} {actionKey} {directionKey} {sp.name}");
                                var idx = (actionKey * MAX_SPRITE_DIRECTION + directionKey) * MAX_ANIM_FRAMES + framesNum;
#if USE_PARTICLE_SYSTEM
                                sheet.AddSprite(sp);
#else
                                var tex = sp.texture;
                                var w = tex.width;
                                var h = tex.height;
                                Rect r = sp.rect;
                                var texRect = new float4(r.xMin / w, r.yMin / h, r.width / w, r.height / h);
                                var size = (float2)r.size;
                                var offset = (float2)sp.pivot / size;
                                size = size / ANIM_PIXEL_PER_UNIT;

                                spriteAnimTextureRect[idx] = texRect;
                                spriteAnimFrameSize[idx] = size;
                                spriteAnimFrameOffset[idx] = offset;
#endif

                                changeColorOffsetX[idx] = data.GetOffset(0).x;
                                changeColorOffsetY[idx] = data.GetOffset(0).y;
                                changeColorOffsetX2[idx] = data.GetOffset(1).x;
                                changeColorOffsetY2[idx] = data.GetOffset(1).y;
                                if (isSpecialCountAtlas)
                                {
                                    changeColorOffsetX[idx + specialCountAtlasOffset] = data.GetOffset(2).x;
                                    changeColorOffsetY[idx + specialCountAtlasOffset] = data.GetOffset(2).y;
                                    changeColorOffsetX2[idx + specialCountAtlasOffset] = data.GetOffset(3).x;
                                    changeColorOffsetY2[idx + specialCountAtlasOffset] = data.GetOffset(3).y;
                                }
                                /*if (CreatorTeam == 0)
                                {
                                    changeColorOffsetX[idx] = data.offset1.x;//EffectMeshUtility.V2Tofloat(data.offset1.x, data.offset1.y);//data.offset1.x;
                                    changeColorOffsetY[idx] = data.offset1.y;//EffectMeshUtility.V2Tofloat(data.startOffset.x, data.startOffset.y);//data.offset1.y;
                                }
                                else if (CreatorTeam == 1)
                                {
                                    changeColorOffsetX[idx] = data.offset2.x;//EffectMeshUtility.V2Tofloat(data.offset1.x, data.offset1.y);//data.offset1.x;
                                    changeColorOffsetY[idx] = data.offset2.y;//EffectMeshUtility.V2Tofloat(data.startOffset.x, data.startOffset.y);//data.offset1.y;
                                }
                                else
                                {
                                    changeColorOffsetX[idx] = 0;
                                    changeColorOffsetY[idx] = 0;
                                }*/
                                startOffsetX[idx] = data.changeColorUV.x;//EffectMeshUtility.V2Tofloat(data.changeColorUV.x, data.changeColorUV.y);
                                startOffsetY[idx] = data.changeColorUV.y;//EffectMeshUtility.V2Tofloat(data.changeColorUV.width, data.changeColorUV.height);
                                rectWidth[idx] = data.changeColorUV.width;
                                rectHeight[idx] = data.changeColorUV.height;
                            }

                            //算出在数组中的位置
                            int pos = actionKey * MAX_SPRITE_DIRECTION + directionKey;
#if USE_PARTICLE_SYSTEM
                            float duration = spLen / FRAME_PER_SECOND * DURATION_EXTEND;
                            startAliveTimePercents[pos] = (startTime + 0.1f / FRAME_PER_SECOND * DURATION_EXTEND) * 100 / allLifeTime;
                            startTime += duration;
                            endAliveTimePercents[pos] = (startTime - 0.0f / FRAME_PER_SECOND * DURATION_EXTEND ) * 100 / allLifeTime;
#else
                            spriteAnimFrameCount[pos] = spLen;
#endif
                        //Debug.Log($"Sprite 结算时间: {pos} duration: {duration} allLeft: {allLifeTime} startTime:{startAliveTimePercents[pos]} endTime:{endAliveTimePercents[pos]}");

                    }
                }
            }

            if (animIndex == 0)
            {
                Debug.LogError($"没有解析到序列帧数据，请检查代码: {spritesAnimationX.assetName}");
            }

            haveUsed = true;

            //SetAnimationData(SpriteAnimData);
        }
        

        //检测当前数组是否需要扩容，如需扩容需要扩增多大空间
        private void CheckAndFixArray(int add_count = 1)
        {
#if USE_PARTICLE_SYSTEM
            //UnityEngine.Profiling.Profiler.BeginSample("CheckAndFixArray_" + particlePool.Length);
            int count = particleCount + add_count;
            //int add_capacity = Mathf.Max(count - particlePool.Length, EXTENT_CAPACITY);

            if (count > particlePool.Length)
            {
                ParticleSystem.Particle[] all = new ParticleSystem.Particle[particlePool.Length * 2];
                for (int i = 0; i < particlePool.Length; i++)
                {
                    all[i] = particlePool[i];
                }

                particlePool = all; //all.ToArray();s
            }

            //UnityEngine.Profiling.Profiler.EndSample();
#endif
        }

        protected AnimSprite AddParticleFromUnitPars(string m_spriteName)
        {
            //Profiler.BeginSample("AddParticle");
            if (systemGo.activeSelf == false)
            {
                systemGo.SetActive(true);

                //UnityEngine.Profiling.Profiler.BeginSample("SetTextureSheetAnimation");
                SetTextureSheetAnimation(false);
                //UnityEngine.Profiling.Profiler.EndSample();
            }
            
            if (particleCount >= SpriteParticleSystemManager.INITAL_PARTICLE_NUM)
            {
                Debug.LogError("超过了单个粒子的最大数目 " + SpriteParticleSystemManager.INITAL_PARTICLE_NUM);
                return null;
            }

            
            //Profiler.EndSample();

            //Profiler.BeginSample("SetSpritesUseTag");
            resourceManager.SetSpritesUseTag(AltasName, 1);

            //Profiler.EndSample();
            //Profiler.BeginSample("CheckAndFixArray");
            if (particleCount >= poolLength)
            {
                ExpendArrays();
            }
            //CheckAndFixArray();
            SpriteVisitor sprite = MemoryPoolMgr.Instance.GetSpriteVisitor();
            //Profiler.EndSample();
            //Profiler.BeginSample("Sprite");
            var spriteIndex = GOTSpritePool.Count;
            sprite.spriteIndex = spriteIndex;

            //{
            sprite.SpriteName = m_spriteName;
            sprite.SpriteNameHashCode = m_spriteName.GetHashCode();
            sprite.active = true;
            //};
            sprite.SetSystemNode_v(this, visitKey);
            //Profiler.EndSample();
            //Profiler.BeginSample("NewPT");
            //UnityEngine.Profiling.Profiler.EndSample();
#if USE_PARTICLE_SYSTEM
            ParticleSystem.Particle pt = new ParticleSystem.Particle
            {
                position = new Vector3(-1000, -1000, -1000),
                angularVelocity = 0f,
                rotation3D = rotation3D,
                velocity = Vector3.zero,
                startColor = Color.white,
                startLifetime = allLifeTime,
                remainingLifetime = allLifeTime,
                startSize3D = Vector3.one
            };
            sprite.particle = pt;
            //Profiler.EndSample();
            //Profiler.BeginSample("AddToPool");
            //particlePool[particleCount] = pt;
#endif
            particleCount++;
            
            GOTSpritePool.Add(sprite);
            //Profiler.EndSample();
            //Profiler.BeginSample("Emit");
#pragma warning disable 618
            //如果这一帧被标记为移除，那就不新创建了，不然会多一个不受控制的“野粒子”
            if (!data.removes[spriteIndex])
            {
#if USE_PARTICLE_SYSTEM
                ptSystem.Emit(pt);
#endif
            }
            else
            {
                data.removes[spriteIndex] = false;
            }
#pragma warning restore 618

            //Profiler.EndSample();
            return sprite;
        }

        private Vector3 _originPos = new Vector3(-1000, -1000, -1000);
        protected AnimSprite[] AddParticleFromUnitPars(int count, string m_spriteName)
        {
            if (systemGo.activeSelf == false)
            {
                systemGo.SetActive(true);
                SetTextureSheetAnimation(false);
            }

            resourceManager.SetSpritesUseTag(AltasName, (uint) count);
            CheckAndFixArray(count);
            SpriteVisitor[] sprite = new SpriteVisitor[count];
            ParticleSystem.Particle pt;
            for (int index = 0; index < count; index++)
            {
                if (particleCount >= SpriteParticleSystemManager.INITAL_PARTICLE_NUM)
                {
                    Debug.LogError("超过了单个粒子的最大数目 " + SpriteParticleSystemManager.INITAL_PARTICLE_NUM);
                    return sprite;
                }

                //UnityEngine.Profiling.Profiler.BeginSample("newSpriteVisitor");
                sprite[index] = MemoryPoolMgr.Instance.GetSpriteVisitor();
                var spriteIndex = GOTSpritePool.Count;
                // 用来标记自己在池子中的位置
                sprite[index].spriteIndex = spriteIndex;
                sprite[index].SpriteName = m_spriteName;
                sprite[index].SpriteNameHashCode = m_spriteName.GetHashCode();
                sprite[index].active = true;
                sprite[index].SetSystemNode_v(this, visitKey);
                //激活

//UnityEngine.Profiling.Profiler.EndSample();
#if USE_PARTICLE_SYSTEM
                pt = new ParticleSystem.Particle
                {
                    position = _originPos,
                    angularVelocity = 0f,
                    rotation3D = rotation3D,
                    velocity = Vector3.zero,
                    startColor = Color.white,
                    startLifetime = allLifeTime,
                    remainingLifetime = allLifeTime,
                    startSize3D = Vector3.one
                };
                sprite[index].particle = pt;
#endif
                //particlePool[particleCount] = pt;
                particleCount++;
                //添加到池子里
                GOTSpritePool.Add(sprite[index]);
#pragma warning disable 618
                //如果这一帧被标记为移除，那就不新创建了，不然会多一个不受控制的“野粒子”
                if (!data.removes[spriteIndex])
                {
#if USE_PARTICLE_SYSTEM
                    ptSystem.Emit(pt);
#endif
                }
                else
                {
                    data.removes[spriteIndex] = false;
                }
                //customDataList.Add(new Vector4(Random.Range(0,1f),Random.Range(0,1f),Random.Range(0,1f),1));
                //ptSystem.SetCustomParticleData(customDataList,ParticleSystemCustomData.Custom1);
#pragma warning restore 618
            }


            return sprite;
        }

        protected void ForceRemoveParticle(List<AnimSprite> sprites)
        {
            if (systemGo != null)
            {
                for (int index = 0; index < sprites.Count; index++)
                {
                    var sprite = sprites[index];
                    int spriteIndex = sprite.spriteIndex;
                    var last = GOTSpritePool[particleCount - 1];
                    last.SetSpriteIndex(spriteIndex);
                    GOTSpritePool[spriteIndex] = last;
                    GOTSpritePool.RemoveAt(particleCount - 1);

                    MemoryPoolMgr.Instance.RecoverItem((SpriteVisitor) sprite);
                    particleCount--;
                }

                if (systemGo.activeSelf == false)
                {
                    if (particleCount > 0)
                    {
                        systemGo.SetActive(true);
                        SetTextureSheetAnimation(false);
                    }
                }
            }
        }

        protected int ForceRemoveParticle(AnimSprite sprite)
        {
            if (systemGo != null)
            {
                int spriteIndex = sprite.spriteIndex;
                var last = GOTSpritePool[particleCount - 1];
                var oldIndex = last.spriteIndex;
                // 设置spriteIndex，并复制属性
                last.SetSpriteIndex(spriteIndex);
                // 这里设置spriteIndex，只是用于Dispose时正确设置remove[spriteIndex]，不需要复制其他属性
                
                sprite.spriteIndex = particleCount - 1;
                GOTSpritePool[spriteIndex] = last;
                GOTSpritePool.RemoveAt(particleCount - 1);

                MemoryPoolMgr.Instance.RecoverItem((SpriteVisitor) sprite);
                particleCount--;

                if (systemGo.activeSelf == false)
                {
                    if (particleCount > 0)
                    {
                        systemGo.SetActive(true);
                        SetTextureSheetAnimation(false);
                    }
                }
                return oldIndex;
            }

            return -1;
        }

        private float spriteScale = 0;
        

        private bool useJob = true;

        public JobHandle jobHandle;

        private float cameraRotation = 45;

        public void SetCameraRotation(float rotation)
        {
            cameraRotation = rotation;
        }

        //每帧结算
        public void CompleteJob()
        {
            jobHandle.Complete();
            //!USE_PARTICLE_SYSTEM
            Draw();
        }

        public void SetEnabled(bool enabled)
        {
#if USE_PARTICLE_SYSTEM
            if (!enabled)
            {
                ptSystem.Pause();
            }
            else
            {
                ptSystem.Play();
            }
            //psJobHandler.enabled = enabled;
#endif
        }
        public JobHandle Schedule()
        {
#if USE_PARTICLE_SYSTEM
            if (ptSystem.particleCount == 0)
            {
                systemGo.SetActive(false);
                //RemoveTextureSheetAnimation();
                return jobHandle;
            }

            if (useJob)
            {
                //jobHandle.Complete();
                var job = new UpdateParticleJob
                {
                    //Time.deltaTime 在DURATION_EXTEND的allLifeTime中占了多少百分比
                    customLifetime = SquareDataManager.CustomLifeTime,
                    deltaTime = Time.deltaTime * DURATION_EXTEND * 100 / allLifeTime,
                    isDirect16 = isDirect16,
                    data = data,
                    startAliveTimePercents = startAliveTimePercents,
                    endAliveTimePercents = endAliveTimePercents,
                    realAliveTimePercents = realAliveTimePercents,
                    changeColorOffsetX = changeColorOffsetX,
                    changeColorOffsetY = changeColorOffsetY,
                    changeColorOffsetX2 = changeColorOffsetX2,
                    changeColorOffsetY2 = changeColorOffsetY2,
                    startOffsetX = startOffsetX,
                    startOffsetY = startOffsetY,
                    rectWidth = rectWidth,
                    rectHeight = rectHeight,
                    allLifeTime = allLifeTime,
                };

                //jobHandle = job.Schedule(ptSystem);
                jobHandle = job.ScheduleBatch(ptSystem, 2048);
            }
#else
            if (particleCount == 0)
            {
                jobHandle = new JobHandle();
                return jobHandle;
            }

            var job = new UpdateTroopsJob
            {
                deltaTime = Time.deltaTime,
                isDirect16 = isDirect16,
                cameraRotation = cameraRotation,
                data = data,
#if USE_PARTICLE_SYSTEM
                startAliveTimePercents = startAliveTimePercents,
                endAliveTimePercents = endAliveTimePercents,
                realAliveTimePercents = realAliveTimePercents,
                allLifeTime = allLifeTime,
#else
                spriteAnimTextureRect = spriteAnimTextureRect,
                spriteAnimFrameSize = spriteAnimFrameSize,
                spriteAnimFrameOffset = spriteAnimFrameOffset,
                spriteAnimFrameCount = spriteAnimFrameCount,
                spriteCurrentFrame = spriteCurrentFrame,
                spriteTimeLeft = spriteTimeLeft,
#endif
                changeColorOffsetX = changeColorOffsetX,
                changeColorOffsetY = changeColorOffsetY,
                changeColorOffsetX2 = changeColorOffsetX2,
                changeColorOffsetY2 = changeColorOffsetY2,
                startOffsetX = startOffsetX,
                startOffsetY = startOffsetY,
                rectWidth = rectWidth,
                rectHeight = rectHeight,
                matrices = matrices,
                specialCountAtlasOffset = specialCountAtlasOffset,
            };
            //*
            jobHandle = job.ScheduleBatch(particleCount, 2048);
            /*/ job.Execute(0, particleCount); //*/
#endif

            return jobHandle;
        }

        #region AnimSpriteCreatorData

        private AnimSpriteCreatorData data;

#if USE_PARTICLE_SYSTEM
        public NativeArray<float> startAliveTimePercents;
        public NativeArray<float> endAliveTimePercents;
        public NativeArray<float> realAliveTimePercents;
#else
        public NativeArray<float4> spriteAnimTextureRect;
        public NativeArray<float2> spriteAnimFrameSize;
        public NativeArray<float2> spriteAnimFrameOffset;
        public NativeArray<int> spriteAnimFrameCount;
        public NativeArray<int> spriteCurrentFrame;
        public NativeArray<float> spriteTimeLeft;
#endif

        public NativeArray<float> changeColorOffsetX;
        public NativeArray<float> changeColorOffsetY;
        public NativeArray<float> changeColorOffsetX2;
        public NativeArray<float> changeColorOffsetY2;
        public NativeArray<float> startOffsetX;
        public NativeArray<float> startOffsetY;
        public NativeArray<float> rectWidth;
        public NativeArray<float> rectHeight;
        public ref AnimSpriteCreatorData GetData()
        {
            return ref data;
        }

#endregion

        private void Draw()
        {
#if !USE_PARTICLE_SYSTEM
            if (!SystemInfo.supportsInstancing)
            {
                return;
            }
            if (particleCount == 0) return;
            if (s_mesh == null)
            {
                s_mesh = CreateSquareMesh();
            }
            jobHandle.Complete();
            const int MaxPerDraw = 1023;
            if (cacheMatrices == null || cacheMatrices.Length < matrices.Length && cacheMatrices.Length < MaxPerDraw)
            {
                cacheMatrices = new Matrix4x4[matrices.Length];
            }
            var count = math.min(particleCount, MaxPerDraw);
            NativeArray<Matrix4x4>.Copy(matrices, cacheMatrices, count);

            var manager = HRenderSettingsManager.Get();
            var dmidata = manager.GetData<HDrawMeshInstData>();

            var gpuInstanceInfo = DrawMeshInstInfo.New(s_mesh, 0, particlesMaterial, 1, cacheMatrices, mbp, count);
            dmidata.m_instInfos.Add(gpuInstanceInfo);
            gpuInstanceInfo = DrawMeshInstInfo.New(s_mesh, 0, particlesMaterial, 0, cacheMatrices, mbp, count);
            dmidata.m_instInfos.Add(gpuInstanceInfo);
#endif
        }

        Mesh CreateSquareMesh()
        {
            var mesh = new Mesh();
            mesh.vertices = new Vector3[] { Vector3.zero, new Vector3(1, 0), new Vector3(0, 1), new Vector3(1, 1) };
            //mesh.vertices = new Vector3[] { Vector3.zero, Vector3.right, Vector3.up, Vector3.right + Vector3.up, };
            mesh.uv = new Vector2[] { Vector2.zero, new Vector2(1, 0), new Vector2(0, 1), Vector2.one };
            mesh.SetIndices(new int[] { 0, 1, 2, 2, 1, 3 }, MeshTopology.Triangles, 0);
            mesh.UploadMeshData(true);
            return mesh;
        }
    }
}
